<script setup lang="ts">
import { ref } from 'vue'
import * as mars3d from 'mars3d'
// @ts-ignore
import { toGeoJSON } from "../utils/index";

type ImportMode = 'kml-normal' | 'kml-flight' | 'kmz-dji'

const importing = ref(false)
const inputRef = ref<HTMLInputElement | null>(null)
const currentMode = ref<ImportMode>('kmz-dji')

function triggerSelect(mode: ImportMode) {
  currentMode.value = mode
  inputRef.value?.click()
}

interface WaylineFrom {
  Placemark: Array<any>
  positionsArr: number[][]
  takeOffRefPoint: string
  takeOffRefPointAGLHeight: number
  takeOffSecurityHeight: number
  flyToWaylineMode: string
  waylineCoordinateSysParam: { heightMode: 'EGM96' | 'relativeToStartPoint' | 'aboveGroundLevel' }
  globalWaypointTurnMode: string
  autoFlightSpeed: number
  finishAction: string
  globalHeight: number
  payloadParam: { imageFormat: string }
  globalWaypointHeadingParam: { waypointHeadingMode: string }
  distance?: number
  duration?: number
  droneInfo?: { droneEnumValue: number }
  payloadInfo?: { payloadEnumValue: number }
}

async function onFileChange(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return
  importing.value = true
  try {
    const ext = file.name.toLowerCase().split('.').pop() || ''
    if (currentMode.value === 'kmz-dji' || ext === 'kmz') {
      await importKmzDji(file)
    } else if (currentMode.value === 'kml-flight') {
      await importKmlFlight(file)
    } else {
      await importKmlNormal(file)
    }
  } finally {
    importing.value = false
    ;(e.target as HTMLInputElement).value = ''
  }
}

async function importKmzDji(file: File) {
  return toGeoJSON(file).then(async (data:any) => {
    console.log('data', data) 
    const normalizeHeightMode = (m: string | undefined) => {
      if (!m) return 'EGM96'
      const s = String(m).toLowerCase()
      if (s.includes('egm')) return 'EGM96'
      if (s.includes('start')) return 'relativeToStartPoint'
      if (s.includes('ground') || s.includes('agl')) return 'aboveGroundLevel'
      return (m as any)
    }

    // 构建基础对象
    const from = createBaseFrom()

    // 映射 DJI wpml 字段 → 本地结构
    try { from.autoFlightSpeed = Number(data?.autoFlightSpeed ?? from.autoFlightSpeed) } catch {}
    try { from.flyToWaylineMode = data?.flyToWaylineMode || from.flyToWaylineMode } catch {}
    try { from.finishAction = data?.finishAction || 'goHome' } catch {}
    try { from.takeOffSecurityHeight = Number(data?.takeOffSecurityHeight ?? from.takeOffSecurityHeight) } catch {}
    try { from.takeOffRefPointAGLHeight = Number(data?.takeOffRefPointAGLHeight ?? from.takeOffRefPointAGLHeight) } catch {}
    try { from.globalWaypointTurnMode = data?.globalWaypointTurnMode || from.globalWaypointTurnMode } catch {}
    try { from.globalWaypointHeadingParam.waypointHeadingMode = data?.globalWaypointHeadingParam?.waypointHeadingMode || from.globalWaypointHeadingParam.waypointHeadingMode } catch {}
    try { from.payloadParam.imageFormat = data?.payloadParam?.imageFormat || from.payloadParam.imageFormat } catch {}
    try { from.distance = Number(data?.distance ?? from.distance ?? 0) } catch {}
    try { from.duration = Number(data?.duration ?? from.duration ?? 0) } catch {}
    try { from.waylineCoordinateSysParam.heightMode = normalizeHeightMode(data?.waylineCoordinateSysParam?.heightMode || data?.executeHeightMode) as any } catch {}
    try { from.globalHeight = Number(data?.globalHeight ?? from.globalHeight) } catch {}
    try { if (typeof data?.takeOffRefPoint === 'string' && data.takeOffRefPoint) from.takeOffRefPoint = data.takeOffRefPoint } catch {}

    // 读取坐标
    let coords: any[] | undefined
    if (data && Array.isArray(data.features)) {
      const line = data.features.find((f: any) => f?.geometry?.type === 'LineString')
      if (line) coords = (line.geometry as any).coordinates
    }
    if (!coords && Array.isArray(data?.positionsArr) && data.positionsArr.length > 0) coords = data.positionsArr
    if (!coords && Array.isArray(data?.Placemark) && data.Placemark.length > 0) {
      coords = data.Placemark.map((pm: any) => {
        const [lng, lat, alt] = String(pm?.Point?.coordinates || '').split(',').map((v: string) => Number(v))
        return [lng || 0, lat || 0, Number(pm?.ellipsoidHeight ?? alt ?? 0)]
      })
    }
    if (!coords || coords.length === 0) throw new Error('未解析到有效航线坐标')
    from.positionsArr = coords.map((pos) => [Number((pos as any)[0] ?? 0), Number((pos as any)[1] ?? 0), Number((pos as any)[2] ?? 0)])

    // 航点：优先采用 wpml 的 Placemark 参数
    if (Array.isArray(data?.Placemark) && data.Placemark.length > 0) {
      from.Placemark = data.Placemark.map((pm: any, index: number) => ({
        ...pm,
        index: String(index),
        useGlobalHeight: pm?.useGlobalHeight ?? '1',
        height: Number(pm?.height ?? pm?.ellipsoidHeight ?? 0),
        waypointSpeed: String(Number(pm?.waypointSpeed ?? from.autoFlightSpeed)),
        actionGroup: Array.isArray(pm?.actionGroup) ? pm.actionGroup : [],
      }))
    } else {
      from.Placemark = from.positionsArr.map((p, index) => placemarkOf(p, index, from.autoFlightSpeed))
    }

    // 将 toGeoJSON 的全部字段合并进实例，确保后续编辑可读取到原始wpml信息
    const merged: any = { ...data, ...from }
    await finalizeRenderAndSave(file, merged)
  })
}

async function importKmlNormal(file: File) {
  const text = await file.text()
  // 优先读取 LineString；否则回退到 Placemark Point
  let coords: number[][] | undefined = extractLineStringCoords(text)
  if (!coords || coords.length === 0) {
    coords = extractPlacemarkPointCoords(text)
  }
  if (!coords || coords.length === 0) throw new Error('未解析到有效KML几何')

  const from = createBaseFrom()
  from.positionsArr = coords.map((p) => [Number(p[0] || 0), Number(p[1] || 0), Number(p[2] || 0)])
  from.Placemark = from.positionsArr.map((p, i) => placemarkOf(p, i, from.autoFlightSpeed))
  await finalizeRenderAndSave(file, from)
}

async function importKmlFlight(file: File) {
  const text = await file.text()
  const wayline = extractDjiWaylineFromKml(text)
  console.log('wayline', wayline) 
  const from = createBaseFrom()
  from.positionsArr = (wayline.positionsArr || []).map((p:any) => [Number(p[0]||0), Number(p[1]||0), Number(p[2]||0)])
  if (!from.positionsArr.length) throw new Error('未解析到飞控KML航点')
  from.Placemark = (wayline.Placemark || []).map((pm:any, i:number) => ({
    ...pm,
    index: String(i),
    useGlobalHeight: pm.useGlobalHeight ?? '1',
    height: Number(pm.height ?? pm.ellipsoidHeight ?? 0),
    waypointTurnParam: pm.waypointTurnParam || { waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature', waypointTurnDampingDist: '0.2' },
    waypointSpeed: String(pm.waypointSpeed ?? from.autoFlightSpeed),
    actionGroup: pm.actionGroup || []
  }))
  // 同步飞控“飞行速度”：取首个航点的 waypointSpeed 作为全局速度（WaylineEditor 会同步到 flightControl.speed）
  try {
    const firstSpd = Number(((from.Placemark?.[0] as any)?.waypointSpeed) ?? ((wayline.Placemark?.[0] as any)?.waypointSpeed))
    if (Number.isFinite(firstSpd) && firstSpd > 0) {
      from.autoFlightSpeed = firstSpd
    }
  } catch {}
  // 使飞控参数中的“飞行高度”与导入的 Placemark.height 对应：
  // 取首个航点的高度作为全局飞行高度（WaylineEditor 会将 globalHeight 同步到 flightControl.altitude）
  try {
    const firstH = Number((from.Placemark?.[0] as any)?.height)
    if (Number.isFinite(firstH)) {
      from.globalHeight = firstH
    }
  } catch {}
  await finalizeRenderAndSave(file, from)
}

function createBaseFrom(): WaylineFrom {
  return {
    Placemark: [],
    positionsArr: [],
    takeOffRefPoint: '',
    takeOffRefPointAGLHeight: 0,
    takeOffSecurityHeight: 0,
    flyToWaylineMode: 'safely',
    waylineCoordinateSysParam: { heightMode: 'EGM96' },
    globalWaypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
    autoFlightSpeed: 5,
    finishAction: 'goHome',
    globalHeight: 50,
    payloadParam: { imageFormat: 'wide,zoom' },
    globalWaypointHeadingParam: { waypointHeadingMode: 'followWayline' },
  }
}

function placemarkOf(p: number[], index: number, speed: number) {
  return {
    Point: { coordinates: `${p[0]},${p[1]},${p[2]}` },
    index: String(index),
    useGlobalHeight: '1',
    height: p[2],
    waypointTurnParam: { waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature', waypointTurnDampingDist: '0.2' },
    waypointSpeed: String(speed),
    actionGroup: [],
  }
}

async function finalizeRenderAndSave(file: File, from: WaylineFrom) {
  const map: mars3d.Map = (window as any).map
  if (!map) throw new Error('地图未初始化')

  const first = from.positionsArr[0]!
  // 优先使用KMZ(wpml)中提供的起飞点；否则用首点地面高生成
  if (!from.takeOffRefPoint || String(from.takeOffRefPoint).trim() === '') {
    const takeoffGround = await mars3d.PointUtil.getSurfaceHeight(map.scene, [first[0], first[1]] as any).then(r => r.height)
    from.takeOffRefPoint = `${first[1]},${first[0]},${takeoffGround}`
  }

  if (from.waylineCoordinateSysParam.heightMode === 'aboveGroundLevel') {
    for (let i = 0; i < from.positionsArr.length; i++) {
      const p = from.positionsArr[i]
      const [lng, lat] = p
      const ground = await mars3d.PointUtil.getSurfaceHeight(map.scene, [lng, lat] as any).then(r => r.height)
      const pointHeight = Number((from.Placemark[i] as any)?.height) || 0
      p[2] = ground + pointHeight
      from.positionsArr[i] = p
    }
  } else if (from.waylineCoordinateSysParam.heightMode === 'relativeToStartPoint') {
    const qfd = from.takeOffRefPoint.split(',').map(v => Number(v)) as [number, number, number]
    for (let i = 0; i < from.positionsArr.length; i++) {
      const p = from.positionsArr[i]
      const pointHeight = Number((from.Placemark[i] as any)?.height) || 0
      p[2] = Number(qfd[2] ?? 0) + Number(from.takeOffRefPointAGLHeight ?? 0) + pointHeight
      from.positionsArr[i] = p
    }
  } else {
    for (let i = 0; i < from.positionsArr.length; i++) {
      const p = from.positionsArr[i]
      const pointHeight = Number((from.Placemark[i] as any)?.height) || 0
      p[2] = pointHeight
      from.positionsArr[i] = p
    }
  }

  const layer: mars3d.layer.GraphicLayer = (window as any).graphicLayer
  if (layer) {
    layer.clear()
    from.positionsArr.forEach((pos, idx) => {
      const [lng, lat, alt] = pos as [number, number, number]
      new mars3d.graphic.PointEntity({ position: [lng, lat, alt], attr: { name: `航点${idx + 1}`, index: idx }, style: { color: '#00ffff', pixelSize: 10, clampToGround: false } }).addTo(layer)
    })
    const line = new mars3d.graphic.PolylineEntity({ positions: from.positionsArr, name: 'road', style: { width: 3, color: '#1a9850' } })
    layer.addGraphic(line)
    line.flyTo()
    ;(from as any).distance = line.distance
  }

  localStorage.setItem('wayLine', JSON.stringify(from))
  const listRaw = localStorage.getItem('wayLineList')
  const list = listRaw ? JSON.parse(listRaw) : []
  const id = `${Date.now()}`
  const name = (file as any).name || '未命名航线'
  list.unshift({ id, name, createdAt: Date.now() })
  localStorage.setItem('wayLineList', JSON.stringify(list))
  localStorage.setItem(`wayLine:${id}`, JSON.stringify(from))
  window.dispatchEvent(new CustomEvent('wayLineList:updated'))
}

function extractLineStringCoords(kmlText: string): number[][] | undefined {
  const re = /<LineString[\s\S]*?<coordinates>([\s\S]*?)<\/coordinates>[\s\S]*?<\/LineString>/i
  const m = kmlText.match(re)
  if (!m) return undefined
  const coordText = m[1]
  const tuples = coordText.split(/\s+/).map(s => s.trim()).filter(Boolean)
  return tuples.map(t => t.split(',').map(n => Number(n))).map(a => [a[0]||0, a[1]||0, a[2]||0])
}

function extractPlacemarkPointCoords(kmlText: string): number[][] {
  const coords: number[][] = []
  const re = /<Placemark[\s\S]*?<Point>[\s\S]*?<coordinates>([\s\S]*?)<\/coordinates>[\s\S]*?<\/Point>[\s\S]*?<\/Placemark>/gi
  let m: RegExpExecArray | null
  while ((m = re.exec(kmlText)) !== null) {
    const parts = m[1].trim().split(',').map(s => Number(s))
    coords.push([parts[0]||0, parts[1]||0, parts[2]||0])
  }
  return coords
}

function extractDjiWaylineFromKml(kmlText: string) {
  const waypoints: any[] = []
  const positions: number[][] = []
  const placemarkRegex = /<Placemark[\s\S]*?<Point>[\s\S]*?<coordinates>([\s\S]*?)<\/coordinates>[\s\S]*?<\/Point>[\s\S]*?<\/Placemark>/gi
  let match
  let idx = 0
  while ((match = placemarkRegex.exec(kmlText)) !== null) {
    const coordText = match[1].trim()
    const parts = coordText.split(',').map(s => parseFloat(s))
    const lng = parts[0]
    const lat = parts[1]
    const alt = parts[2] ?? 0
    positions.push([lng, lat, alt])
    waypoints.push({
      Point: { coordinates: coordText },
      index: String(idx++),
      useGlobalHeight: '1',
      ellipsoidHeight: String(alt),
      height: alt,
      useGlobalSpeed: '1',
      waypointSpeed: '10',
      useGlobalHeadingParam: '1',
      waypointHeadingParam: {
        waypointHeadingMode: 'followWayline',
        waypointHeadingAngle: '0',
        waypointHeadingPathMode: 'followBadArc',
        waypointPoiPoint: '0,0,0',
        waypointHeadingPoiIndex: '0'
      },
      useGlobalTurnParam: '1',
      waypointTurnParam: {
        waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
        waypointTurnDampingDist: '0.2'
      },
      useStraightLine: '1',
      gimbalPitchAngle: '0',
      actionGroup: []
    })
  }
  return { Placemark: waypoints, positionsArr: positions }
}
</script>

<template>
  <div class="header-importer">
    <input ref="inputRef" type="file" accept=".kml,.kmz" style="display:none" @change="onFileChange" />
    <a-dropdown>
      <a-button :loading="importing">导入</a-button>
      <template #overlay>
        <a-menu selectable>
          <a-menu-item key="kml-normal" @click="() => triggerSelect('kml-normal')">导入KML（普通）</a-menu-item>
          <a-menu-item key="kml-flight" @click="() => triggerSelect('kml-flight')">导入KML（飞控）</a-menu-item>
          <a-menu-item key="kmz-dji" @click="() => triggerSelect('kmz-dji')">导入KMZ（DJI）</a-menu-item>
        </a-menu>
      </template>
    </a-dropdown>
  </div>
  
</template>

<style scoped>
.header-importer { display: inline-flex; align-items: center; }
</style>


